#include <QKeyEvent>
#include <QMouseEvent>
#include <QPainter>
#include <QCoreApplication>

#include <osgViewer/View>
#include "ShxText.h"
#include <osg/Stats>
#include <osg/PrimitiveSet>
#include <osg/LineWidth>

#include "HighlightObjectUnderMouse.h"
#include "CmdManager.h"
#include "QtOSGWidget.h"
#include "OsgUtil.h"
#include "QtUtility.h"
#include "ViewerExt.h"
#include "GLSLPrograms.h"
#include "Ent.h"

osg::ref_ptr<osg::Program> createEdgeProgram2();

void updateLinesInfo(osg::ref_ptr<osg::Geometry> hightlight, const std::vector<std::vector<osg::Vec3d>>& edgePoints)
{
	hightlight->getPrimitiveSetList().clear();

	if (edgePoints.empty())
		return;
	auto pset = new osg::MultiDrawArrays(GL_LINE_STRIP);
	auto va = new osg::Vec3Array();
	int first = 0;
	int count = 0;
	for (const auto& edge : edgePoints)
	{
		if (edge.size() >= 2)
		{
			count = edge.size();
			pset->add(first, count);
			first += count;
			for (const auto& point : edge)
			{
				va->push_back(point);
			}
		}
	}
	hightlight->setVertexArray(va);


	hightlight->addPrimitiveSet(pset);

	hightlight->dirtyGLObjects();
}

HighlightObjectUnderMouse::HighlightObjectUnderMouse(CmdManager *cmdManager, QtOSGWidget *widget3D)
{
	m_cmdManager = cmdManager;
	m_picker = new Qt3DPicker(widget3D);
	auto viewer = dynamic_cast<ViewerExt *>(widget3D->getViewer());
	m_picker->init(viewer, 5);
	m_picker->setPickMode(POINT_MODE);
	m_picker->setTraversalMask(D3SurfaceMask);
	m_picker->selectEntity(false);
	if (viewer)
	{
		m_hightlight = new osg::Geometry();
		m_hightlight->setNodeMask(NoPickMask);
		osg::ref_ptr<osg::Vec4Array> ca = new osg::Vec4Array();
		ca->push_back(osg::Vec4(0, 229.f/255.f, 238.f/255.f, 1.f));

		m_hightlight->setColorArray(ca.get(), osg::Array::BIND_OVERALL);

		osg::ref_ptr<osg::Program> program = createEdgeProgram2();
		auto ss = m_hightlight->getOrCreateStateSet();
		ss->setAttributeAndModes(program, osg::StateAttribute::ON);
		auto lineWidth = new osg::LineWidth(3.0f);
		ss->setAttributeAndModes(lineWidth);

		widget3D->pauseRenderThread();
		viewer->getSceneData()->asGroup()->addChild(m_hightlight);
		widget3D->resumeRenderThread();
	}
}

HighlightObjectUnderMouse::~HighlightObjectUnderMouse()
{
}

bool HighlightObjectUnderMouse::handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa)
{
	if (!m_picker)
		return false;
	if (m_cmdManager && m_cmdManager->currentCmd())
		return false;
	if (ea.getModKeyMask() == 0 && ea.getEventType() == osgGA::GUIEventAdapter::MOVE && ea.getButton() == 0)
	{
		m_picker->setXY1(ea.getX(), ea.getY());
		m_picker->clearSelection();
		auto widget = m_picker->getOSGWidget();
		m_picker->pick(false);
		auto selection = m_picker->GetSelections();
		if (!selection.empty())
		{
			auto node = widget->getPickable(*selection.begin());
			auto ent = static_cast<Ent3DFace*>(node.get());
			if (node != m_lastNode.lock())
			{
				if (ent)
				{
					m_edgePoints = ent->getWCSEdgePoints();
					updateLinesInfo(m_hightlight, m_edgePoints);
				}
				m_lastNode = node;
			}
		}
		else
		{
			if (!m_lastNode.expired())
			{
				m_edgePoints.clear();
				updateLinesInfo(m_hightlight, m_edgePoints);
			}
			m_lastNode.reset();
		}
	}
	return false;
}
